package com.nirvana.utils.json;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
import net.sf.json.util.CycleDetectionStrategy;
import net.sf.json.util.PropertyFilter;
import net.sf.json.util.PropertySetStrategy;

/**
 * json工具类
 * @author Sue
 *
 */
public class JSONUtils {
	
	private static Log log = LogFactory.getLog(JSONUtils.class);
	
	/**
	 * 序列化JsonConfig的配置(bean到Json时使用)
	 * @return
	 */
	private static JsonConfig getSerializableConfig(){	
		JsonConfig jsConfig = new JsonConfig();
		/**是否过滤默认的key,默认为false，即过滤
		 *如map含有一个key，名为class,此时转换成json,如果为false,则class不会输出,如果为true时，则会输出
		 */
		jsConfig.setIgnoreDefaultExcludes(false);
		/**不输出自包含
		 * 也就是一个类里面有一个属性指向它自己，此时转换成json，是否也转换此属性
		 */
		jsConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
		/**
		 * 注册时间类型默认的格式 yyyy-MM-dd
		 */
		jsConfig.registerJsonValueProcessor(Date.class,new DateValueProcessor());
		
		return jsConfig;
	}
	
	/**
	 * 反序列化JsonConfig(JSON到bean时使用)
	 * @return
	 */
	private static JsonConfig getUnSerializableConfig(){
		JsonConfig jsConfig = new JsonConfig();
		//属性赋值策略(默认要bean里面有对应的属性才反列化)
		jsConfig.setPropertySetStrategy(PropertySetStrategy.DEFAULT);
		return jsConfig;
	}
	
	
	
	/**
	 * bean转换成json(bean可以是实体Bean,Collection,数组,Map)
	 * @param obj
	 * @param excludeProperties:排除不序列化成json字符串的属性  jsonConfig.setExcludes(excludeProperties);
	 * @return
	 */
	public static JSON Bean2Json(Object obj,String[] excludeProperties){
		log.info("Bean2Json:" + obj.getClass().getName());		
		if(excludeProperties == null || excludeProperties.length == 0){
			return Bean2Json(obj);
		}else{
			JsonConfig jsConfig = getSerializableConfig();
			jsConfig.setExcludes(excludeProperties);
			JSON json = JSONSerializer.toJSON(obj,jsConfig);
			return json;
		}	
	}
	
	
	/**
	 * 指定具体类型的处理方式
	 * @param t
	 * @param jValueProcessMap：key:类型，value:对应的类型处理器
	 * @return
	 */
	public static<T> JSON Bean2Json(T t,Map<Class<?>,JsonValueProcessor> jValueProcessMap){
		if(jValueProcessMap == null)
			return Bean2Json(t);
		JsonConfig jsConfig = getSerializableConfig();
		for(Map.Entry<Class<?>,JsonValueProcessor> entry:jValueProcessMap.entrySet()){
			jsConfig.registerJsonValueProcessor(entry.getKey(),entry.getValue());
		}
		JSON json = JSONSerializer.toJSON(t,jsConfig);
		return json;
	}
	
	/**
	 * Bean转换成json
	 * @param obj
	 * @param proFilter:属性过滤器:里面可以配忽略的属性
	 * @return
	 */
	public static JSON Bean2Json(Object obj,PropertyFilter proFilter){
		log.info("Bean2Json:" + obj.getClass().getName());
		if(proFilter == null)
			return Bean2Json(obj);
		JsonConfig jsConfig = getSerializableConfig();
		jsConfig.setJsonPropertyFilter(proFilter);
		JSON json = JSONSerializer.toJSON(obj, jsConfig);
		return json;
	}
	
	public static JSON Bean2Json(Object obj){
		log.info("Bean2Json:" + obj.getClass().getName());		
		JsonConfig jsConfig =getSerializableConfig();
		JSON json = JSONSerializer.toJSON(obj,jsConfig);
		return json;
	}
	
	public static JSON Map2Json(Map<String,?> map,String[] excludeKeys){
		return Bean2Json(map, excludeKeys);
	}
	
	public static JSON Collection2Json(Collection<?> collect,String[] excludeProperties){
		return Bean2Json(collect, excludeProperties);
	}
	
	
	
	@SuppressWarnings("unchecked")
	public static<T> T json2Bean(JSON json,Class<T> cls){
		log.info("json2Bean:" + cls.getName());
		JsonConfig javaConfig = getUnSerializableConfig();
		//设置json要转换成的Bean类
		javaConfig.setRootClass(cls);	
		return (T)JSONSerializer.toJava(json, javaConfig);
	}
	
	
	
	/**
	 * JSON转换成普通的Bean
	 * @param json
	 * @param cls
	 * @param propertySetStrategy
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static<T> T json2Bean(JSON json,Class<T> cls,PropertySetStrategy propertySetStrategy){
		if(propertySetStrategy == null)
			return json2Bean(json, cls);
		JsonConfig javaConfig = getUnSerializableConfig();
		javaConfig.setPropertySetStrategy(propertySetStrategy);
		javaConfig.setRootClass(cls);
		return (T)JSONSerializer.toJava(json, javaConfig);
	}
	
	
	@SuppressWarnings("unchecked")
	public static<T> List<T> json2List(JSON json,Class<T> cls){
		JsonConfig unSerializableConfig = getUnSerializableConfig();
		unSerializableConfig.setRootClass(cls);
		unSerializableConfig.setCollectionType(List.class);
		return (List<T>)JSONSerializer.toJava(json, unSerializableConfig);
	}
	
	
	
	@SuppressWarnings("unchecked")
	public static<T> Set<T> json2Set(JSON json,Class<T> cls){
		JsonConfig unSerializableConfig = getUnSerializableConfig();
		unSerializableConfig.setRootClass(cls);
		unSerializableConfig.setCollectionType(Set.class);
		return (Set<T>)JSONSerializer.toJava(json, unSerializableConfig);
	}
	
	
	/**
	 * json转换成普通的Bean
	 * @param json
	 * @param cls
	 * @param map
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T json2Bean(JSON json,Class<T> cls,Map<String,Class<?>> map){
		if(map == null)
			return (T)json2Bean(json, cls);
		JsonConfig javaConfig = getUnSerializableConfig();
		javaConfig.setRootClass(cls);
		javaConfig.setCollectionType(List.class);
		javaConfig.setClassMap(map);
		return (T) JSONSerializer.toJava(json, javaConfig);
	}
	
	
	
	

	
	
	
	
	
	
	
	
	
	
}
